# coding=utf-8
# 全世界最帅的帅哥
from operator import and_

from elasticsearch_dsl import Search
from flask import request
from flask_restful import reqparse

from ysgg1_club_comment.es_client import es
from ysgg1_club_comment.modules import db
from ysgg1_club_comment.modules.auth_user import AuthUser
from ysgg1_club_comment.modules.subject_info import SubjectInfo
from ysgg1_club_comment.modules.subject_mapping import SubjectMapping
from ysgg1_club_subject.constant.redis_prefix import RedisPrefix
from ysgg1_club_subject.handler.subject.subject_type_handler_factory import SubjectTypeHandlerFactory
from ysgg1_club_subject.redis_client import redis_liked_client
from ysgg1_club_subject.subject_serializers.subject_info_serializer import SubjectInfoPaginateSerializer


def query_subject_id_cursor(category_id, label_id, cursor=None, subject_id=None):
    # 基础查询: 关联 subject_info 和 subject_mapping表
    query = db.session.query(SubjectInfo.id).join(
        SubjectMapping, SubjectMapping.subject_id == SubjectInfo.id
    ).filter(
        and_(
            SubjectMapping.category_id == category_id,
            SubjectMapping.label_id == label_id
        )
    )

    if cursor is not None and subject_id is not None:
        if cursor == 1:
            query = query.filter(SubjectInfo.id > subject_id)
        elif not cursor:
            query = query.filter(SubjectInfo.id < subject_id).order_by(SubjectInfo.id.desc())

    # 限制返回结果为 1 条记录
    result = query.offset(0).limit(1).first()

    # 返回结果中的 id，如果没有结果则返回 None
    return result[0] if result else None


def assemble_subject_cursor(subject_id, category_id=None, label_id=None):
    if not category_id or not label_id:
        return [None, None]
    next_subject_id = query_subject_id_cursor(category_id, label_id, cursor=1, subject_id=subject_id)
    last_subject_id = query_subject_id_cursor(category_id, label_id, cursor=0, subject_id=subject_id)

    return next_subject_id, last_subject_id


def query_subject_info():
    parser = reqparse.RequestParser()
    parser.add_argument('subjectId', required=True, help="题目id不能为空")
    args = parser.parse_args()
    subject_id = int(args.subjectId)
    subject_info = SubjectInfo.query.filter(SubjectInfo.id == subject_id, ~SubjectInfo.is_delete).first()
    subject_type = subject_info.subject_type
    # 通过题目类型调用对应的handler
    handler = SubjectTypeHandlerFactory.get_handler(subject_type)
    data = handler.query(subject_info)
    request_data = request.get_json()
    category_id = request_data.get('categoryId', None)
    label_id = request_data.get('labelId', None)
    next_subject_id, last_subject_id = assemble_subject_cursor(subject_id, category_id, label_id)
    data["next_subject_id"] = next_subject_id
    data["last_subject_id"] = last_subject_id
    return data


def query_subject_list():
    parser = reqparse.RequestParser()
    parser.add_argument('categoryId', required=True, help="分类id不能为空")
    parser.add_argument('labelId', required=True, help="分类id不能为空")
    parser.add_argument('pageIndex', required=True, help="页数不能为空")
    parser.add_argument('pageSize', required=False, help="每页个数不能为空")
    parser.add_argument('subjectDifficulty', required=False)
    parser.add_argument('subjectType', required=False)

    args = parser.parse_args()
    category_id = int(args.categoryId)
    label_id = int(args.labelId)
    subject_difficult = args.subjectDifficulty
    subject_type = args.subjectType
    page_index = int(args.pageIndex)
    page_size = int(args.pageSize)

    subject_info_query = (db.session.query(
        SubjectInfo,
        SubjectMapping.category_id,
        SubjectMapping.label_id
    ).join(
        SubjectMapping, SubjectMapping.subject_id == SubjectInfo.id,
    ).filter(
        SubjectMapping.category_id == category_id,
        SubjectMapping.label_id == label_id,
        SubjectInfo.is_delete == 0,  # 注意：这里使用 False 而不是 0，假设 is_delete 是布尔类型
        SubjectMapping.is_delete == 0  # 同样，这里也使用 False
    ))

    if subject_difficult:
        subject_info_query = subject_info_query.filter(SubjectInfo.subject_difficult == subject_difficult)
    if subject_type:
        subject_info_query = subject_info_query.filter(SubjectInfo.subject_type == subject_type)

    subject_info_list = subject_info_query.paginate(page=page_index, per_page=page_size, error_out=False)
    subject_info_data = SubjectInfoPaginateSerializer(subject_info_list).to_dict()

    return subject_info_data


def query_subject_by_es():
    request_data = request.get_json()

    keyword = request_data.get('keyword')
    s = Search(using=es)

    s = s.query("multi_match", query=keyword, fields=["subject_answer", "subject_name^2"])
    s = s.highlight(
        "subject_name",  # 高亮 subject_name 字段
        "subject_answer",  # 高亮 subject_answer 字段
        pre_tags=["<span style = 'color:red'>"],  # 高亮前缀标签
        post_tags=["</span>"]  # 高亮后缀标签
    ).extra(
        from_=0,  # 从第 0 条结果开始
        size=10  # 返回 10 条结果
    )
    response = s.execute()

    return response.to_dict()


def get_contribute_list_by_mysql():
    subject_info_list = SubjectInfo.query.filter(
        SubjectInfo.is_delete == 0,
        SubjectInfo.create_by.isnot(None)
    ).group_by(SubjectInfo.create_by).with_entities(
        db.func.count(1).label('subject_count'),
        SubjectInfo.create_by
    ).limit(5).all()

    contribute_list = []

    for subject_info in subject_info_list:
        user = AuthUser.query.filter_by(user_name=subject_info.create_by, is_delete=0).with_entities(
            AuthUser.nick_name, AuthUser.avatar
        ).first()
        contribute_list.append(
            {
                'nick_name': user.nick_name,
                'avatar': user.avatar,
                'score': subject_info.subject_count
            }
        )
    return contribute_list


def get_contribute_list():
    subject_info_list = redis_liked_client.zrevrange(RedisPrefix.RANK_KEY, 0, 4, withscores=True)
    if not subject_info_list:
        return []

    contribute_list = []

    for element, score in subject_info_list:
        user = AuthUser.query.filter_by(user_name=element.decode("utf8"), is_delete=0).with_entities(
            AuthUser.nick_name, AuthUser.avatar
        ).first()
        if user:
            contribute_list.append(
                {
                    'nick_name': user.nick_name,
                    'avatar': user.avatar,
                    'score': score
                }
            )
    return contribute_list


def error_correction():
    request_data = request.get_json()
    subject_id = request_data.get("subjectId")
    if not subject_id:
        return
    subject_info = SubjectInfo.query.filter(SubjectInfo.subject_id == subject_id).with_entities(
        SubjectInfo.subject_answer, SubjectInfo.subject_parser).first()

    return {
        "subject_parser": subject_info.subject_parser,
        "subject_answer": subject_info.subject_answer
    }
